﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CoreApp.DBModel;
using CoreApp.Utility;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using NLog.Web;

namespace CoreApp.Web
{
    public class Startup
    {
        public IConfiguration Configuration { get; }

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //设置接收文件长度的最大值。
            services.Configure<FormOptions>(x =>
            {
                x.ValueLengthLimit = int.MaxValue;
                x.MultipartBodyLengthLimit = int.MaxValue;
                x.MultipartHeadersLengthLimit = int.MaxValue;
            });

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            services.AddOptions();

            //注册数据库连接串配置实例
            services.Configure<DBConnectionConfig>(Configuration.GetSection("DBConnection"));

            #region 依赖注入
            //（单独依赖注入）ASP.net Core自带的注入方式
            //services.AddScoped<IUserRepository,UserRepository>();//如果依赖注入很多，这种单独注入的方式维护很麻烦。

            /*
             * 批量依赖注入服务(也可以用第三方IOC框架实现批量注入，如：Autofac)
             * 这里注入CoreApp.DapperAccess程序集下的类名后缀为Repository的服务（所以需要引用CoreApp.DapperAccess程序集）
             */
            var dicList = CommonUnit.GetClassAndInterfacePairList("CoreApp.DapperAccess", "Repository");
            foreach (var item in dicList)
            {
                foreach (var typeItem in item.Value)
                {
                    services.AddScoped(typeItem, item.Key);
                }
            }
            #endregion

            //redis
            services.AddDistributedRedisCache(options =>
            {
                //方式一
                // options.InstanceName = Configuration["RedisCache:InstanceName"];
                // options.Configuration = Configuration["RedisCache:RedisConnectionString"];
                //方式二
                options.InstanceName = Configuration.GetSection("RedisCache:InstanceName").Value;
                options.Configuration = Configuration.GetSection("RedisCache:RedisConnectionString").Value;
            });

            #region 配置authorrize登录验证
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            }).AddCookie(options =>
            {
                options.LoginPath = "/Account/Login";
                options.Cookie.Name = "AspnetcoreSessionId";
                options.Cookie.Path = "/"; //cookie所在的目录，asp.net默认为"/"，就是根目录
                options.Cookie.HttpOnly = true; //设置了HttpOnly属性，js脚本将无法读取到cookie信息，能有效的防止XSS攻击窃取cookie内容，增加cookie的安全性
                options.Cookie.Expiration = new TimeSpan(0, 30, 0); //cookie过期时间
                options.ExpireTimeSpan = new TimeSpan(0, 30, 0);
            });
            #endregion
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();//Hsts(HTTP Strict Transport Security Protocol ) 是一个安全功能，它告诉浏览器只能通过HTTPS访问当前资源，而不是HTTP。
            }

            app.UseHttpsRedirection();//强制使用https，把所有的HTTP请求转换为HTTPS
            app.UseStaticFiles();
            app.UseCookiePolicy();// General Data Protection Regulation(通用数据保护条例)

            //配置NLog
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);//这是为了防止中文乱码
            loggerFactory.AddNLog();//添加NLog
            env.ConfigureNLog("nlog.config");//读取Nlog配置文件

            //验证中间件，该中间件一定要放在app.UseMvc前面，否则HttpContext.User.Identity.IsAuthenticated一直为false。
            app.UseAuthentication();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });

            //如果使用nginx反向代理,需要引用Microsoft.AspNetCore.HttpOverrides
            app.UseForwardedHeaders(new ForwardedHeadersOptions
            {
                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
            });
        }

    }
}
